#pragma once

#include <queue>
#include <memory>
#include <mutex>

#include "Schedule.h"

//main thread schedule
class QueueSchedule : public ISchedule
{
public:
    virtual void AddTask(TThreadSafeSharedPtr <CTaskBase> InTask) override;

    bool HasTasks();


    //call this function in main thread
    void DoAllTasks()
    {
        while(!WaitingTasks.empty())
        {
            auto Task=WaitingTasks.front();
            {
                std::lock_guard<std::mutex> Locker(WaitingTasksLocker);
                WaitingTasks.pop();
            }


            Task->State.store(CTaskBase::EState::Executing);
            bool bSucceed= Task->Do();
            if(bSucceed)
            {
                if(Task->NextTask)
                {
                    auto NextTask=Task->NextTask;
                    Task->NextTask=nullptr; //clear next task, prevent circular reference
                    NextTask->AddToSchedule();
                }
            }
            else
            {
                if(Task->FailedTask)
                {
                    auto FailedTask=Task->FailedTask;
                    Task->FailedTask=nullptr; //clear next task, prevent circular reference
                    FailedTask->AddToSchedule();
                }
            }
        }
    }

    void Shutdown();

protected:
    std::mutex WaitingTasksLocker;
    std::queue<TThreadSafeSharedPtr<CTaskBase>> WaitingTasks;
};